/*
	@File: stacktrace.c
	@Date: 2019/06/03
	@Author: Lyrus
	@Description: 
*/

#include "stacktrace.h"

#define INNER_DEEP                  (2)
#define MAX_DEEP                    (24)
#define MAX_ST_INFO                 (256)
#define MAX_ST_LINE                 (512)

int clog_get_curr_proc_handle(clog_st_t *st)
{
#ifdef WIN32
	st->curr_proc = GetCurrentProcess();
	if (NULL == st->curr_proc) 
	{
		return FALSE;
	}

	if (SymInitialize(st->curr_proc, NULL, TRUE) != TRUE) 
	{
		st->curr_proc = NULL;
		return FALSE;
	}
#else
	st->curr_proc = NULL;
#endif
	return TRUE;
}

void clog_write_stacktrace_info(FILE *fp, clog_st_t *st)
{
	unsigned int i = 0;
	unsigned short frames = 0;
	void *stack[MAX_DEEP] = {0};
	char st_line[MAX_ST_LINE] = {0};

#ifdef WIN32
	SYMBOL_INFO *symbol = NULL;

	clog_get_curr_proc_handle(st);

	if (NULL == st->curr_proc) {
		return;
	}

	frames = CaptureStackBackTrace(INNER_DEEP, MAX_DEEP, stack, NULL);
	symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + sizeof(char) * MAX_ST_INFO, 1);
	symbol->MaxNameLen = MAX_ST_INFO - 1;
	symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
	for (i = 0; i < frames; ++i) {
		SymFromAddr(st->curr_proc, (DWORD64)(stack[i]), 0, symbol);
		snprintf(st_line, sizeof(st_line) - 1, "    %d: %s [0x%X]\n", frames - i - 1, symbol->Name, symbol->Address);
		fwrite(st_line, sizeof(char), strlen(st_line), fp);
	}
#else
	char **st_arr = NULL;

	frames = backtrace(stack, MAX_DEEP);
	st_arr = backtrace_symbols(stack, frames);
	for (i = 0; i < frames; ++i) {
		snprintf(st_line, sizeof(st_line) - 1, "    %d: %s\n", frames - i - 1, st_arr[i]);
		fwrite(st_line, sizeof(char), strlen(st_line), fp);
	}
	free(st_arr);
#endif
}